﻿using System;
using System.Collections.Generic;
using System.Text;

namespace E.Y.E.Jobs
{
    public class TaskEnumTypes
    {
        public enum TaskStatus { Waiting, Done, InProgress, Expired };
        public enum TaskPriority { High, Low, None };
        public enum ReminderType { None, Once, Daily, Weekly, Monthly, Yearly };
    }

    public class Task
    {
        private int _ID;
        private string _detail;
        private string _venue;
        private DateTime _startTime;
        private DateTime _endTime;
        private TaskEnumTypes.TaskStatus _status;
        private TaskEnumTypes.TaskPriority _priority;
        private TaskEnumTypes.ReminderType _remindType;
        private TimeSpan _remindBefore;

        public Task()
        {
        }

        public int ID
        {
            get{return _ID;}
            set{ _ID = value;}   
        }

        public string Detail
        {
            get{return _detail;}
            set{ _detail = value;}
        }

        public string Venue
        {
            get{ return _venue;}
            set{ _venue = value;}
        }

        public DateTime StartTime
        {
            get{ return _startTime; }
            set{ _startTime = value;}
        }

        public DateTime EndTime
        {
            get{return _endTime;}
            set{ _endTime = value;}
        }

        public TaskEnumTypes.TaskStatus Status
        {
            get{ return _status; }
            set{_status = value;}
        }

        public TaskEnumTypes.TaskPriority Priority
        {
            get { return _priority; }
            set{_priority = value;}
        }

        public TaskEnumTypes.ReminderType TypeOfReminder
        {
            get { return _remindType; }
            set { _remindType = value; }
        }

        public TimeSpan RemindBefore
        {
            get { return _remindBefore; }
            set { _remindBefore = value; }
        }

        // Check whether the Status should be update.
        public void SelfUpdateStatus()
        {
            bool StartTimeSettingValid = CheckValidTimeSetting(StartTime);
            bool EndTimeSettingValid = CheckValidTimeSetting(EndTime);

            bool InProgress = (DateTime.Compare(StartTime, DateTime.Now) <= 0) && StartTimeSettingValid;
            bool Expired = (DateTime.Compare(EndTime, DateTime.Now) <= 0) && EndTimeSettingValid;

            if (InProgress)
            {
                Status = TaskEnumTypes.TaskStatus.InProgress;
            } 
            
            if (Expired)
            {
                Status = TaskEnumTypes.TaskStatus.Expired;
            }
        }

        // Check the given DateTime is set (not DateTime(0))
        private Boolean CheckValidTimeSetting(DateTime timeSetting)
        {
            Boolean HaveTimeSetting = (timeSetting != new DateTime());
            return HaveTimeSetting;
        }

        // Return a remaining time until start time; -ve if _startTime passed
        public TimeSpan FindDayToStart()
        {
            TimeSpan RemainingTime = GetRemainingTime(_startTime);
            return RemainingTime;
        }

        // Return a remaining time until end time; -ve if _endTime passed
        public TimeSpan FindDayToEnd()
        {
            TimeSpan RemainingTime = GetRemainingTime(_endTime);
            return RemainingTime;
        }

        // Get the remaining time span for target time, Noted that the -ve value is the time is passed.
        private TimeSpan GetRemainingTime(DateTime targetTime)
        {
            TimeSpan RemainTime = targetTime.Subtract(DateTime.Now);
            return RemainTime;
        }

        // Check whether we should alarm for this minitus
        public Boolean ShouldAlarm()
        {
            bool NoNeedRemind = (TypeOfReminder == TaskEnumTypes.ReminderType.None);
            bool FinishedOrExpired = (Status == TaskEnumTypes.TaskStatus.Done || Status == TaskEnumTypes.TaskStatus.Expired);

            if (NoNeedRemind || FinishedOrExpired)
            {
                return false;
            }

            DateTime TargetTime;

            bool IsStartTimeSet = CheckValidTimeSetting(StartTime);
            bool IsEndTimeSet = CheckValidTimeSetting(EndTime);

            if (IsStartTimeSet)
            {
                TargetTime = StartTime;
            }
            else if (IsEndTimeSet)
            {
                TargetTime = EndTime;
            }
            else
            {
                return false;
            }

            bool RemainingTimeSmallerThanOneMinute = ((GetRemainingTime(TargetTime) - RemindBefore).CompareTo(new TimeSpan(0, 1, 0)) <= 0);
            bool RemainingTimeIsPositive = ((GetRemainingTime(TargetTime) - RemindBefore).CompareTo(new TimeSpan(0, 0, 0)) >= 0);
            bool MatchTime = (RemainingTimeSmallerThanOneMinute && RemainingTimeIsPositive);

            if (MatchTime)
            {
                return true;
            }
            return false;
        }

        // Unset the Alarm
        public void UnsetAlarm()
        {
            TypeOfReminder = TaskEnumTypes.ReminderType.None;
        }

        // Constructor (some with default value to enable FLEXIBLE initialization)
        public Task(    int givenID, 
                        string givenDetail,
                        TaskEnumTypes.ReminderType givenRemindType, 
                        string givenVenue = "", 
                        DateTime givenStartTime = new DateTime(), 
                        DateTime givenEndTime = new DateTime(),
                        TaskEnumTypes.TaskPriority givenPriority = TaskEnumTypes.TaskPriority.Low, 
                        TimeSpan givenRemindTime = new TimeSpan()   )
        {
            ID = givenID;
            Detail = givenDetail;
            Venue = givenVenue;
            Priority = givenPriority;
            TypeOfReminder = givenRemindType;
            StartTime = givenStartTime;
            EndTime = givenEndTime;
            RemindBefore = givenRemindTime;

            Status = TaskEnumTypes.TaskStatus.Waiting;
            SelfUpdateStatus();
        }        
    }
}